/**
 *
 * Copyright (c) 2014 BinKylin Studio.
 *
 * Author: TBinkylin
 * Created Date: 2014-03-01
 * 
 * 	version					author					remark
 * 	1.0						benoit				
 */
package net.binkylin.common.utils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DateUtil {

	private static final Logger log = LoggerFactory.getLogger(DatabaseUtil.class);

	public final static String DEFAULT_DATEMILLIS_FORMAT = "dd/MM/yyyy HH:mm:ss.SSS";
	public final static String DEFAULT_DATETIME_FORMAT = "dd/MM/yyyy HH:mm:ss";
	public final static String DEFAULT_DATETIME_AM_FORMAT = "dd/MM/yyyy hh:mm:ss aaa";
	public final static String DATETIME_FORMAT_HHMM = "dd/MM/yyyy HH:mm";
	public final static String DEFAULT_DATE_FORMAT = "dd/MM/yyyy";
	public final static String PRINT_DATE_FORMAT = "yyyyMMdd";
	public final static String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
	public final static String DEFAULT_DATEYYYYDD_FORMAT = "yyyyMMddHHmm";
	public final static String MONTH_FORMAT = "00";

	private static String default_timezone = "Asia/Singapore";

	/**
	 * Returns the date instance based on the current system date and default
	 * timezone.
	 * <p/>
	 * 
	 * @return Current System date.
	 */
	public static Date getDate() {
		TimeZone tz = TimeZone.getTimeZone(default_timezone);
		Calendar calendar = Calendar.getInstance(tz);
		return calendar.getTime();
	}

	/**
	 * Returns the timestamp instance based on the current system date and
	 * default timezone.
	 * 
	 * @return the current timestamp
	 */
	public static Timestamp getCurrentTimestamp() {
		return new Timestamp(getDate().getTime());
	}

	/**
	 * Format the input date to a date time string in the following format: <br>
	 * <code>dd/MM/yyyy HH:mm:ss</code>
	 * 
	 * @param date
	 *            the date time value to be formatted into a date time string.
	 * @return the formatted date time string; an empty String if the input date
	 *         is <code>null</code> or if there is error during formatting.
	 */
	public static String formatDateTime(Date date) {
		String dateTimeStr = "";
		SimpleDateFormat defaultDTF = new SimpleDateFormat(DEFAULT_DATETIME_FORMAT);
		try {
			dateTimeStr = defaultDTF.format(date);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}

		return dateTimeStr;
	}

	public static String formatAMDateTime(Date date) {
		String dateTimeStr = "";
		DateFormat defaultAMDTF = new SimpleDateFormat(DEFAULT_DATETIME_AM_FORMAT);
		try {
			dateTimeStr = defaultAMDTF.format(date);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}

		return dateTimeStr;
	}

	/**
	 * Format the input date to a date time string in the following format: <br>
	 * <code>dd/MM/yyyy HH:mm:ss.SSS</code>
	 * 
	 * @param date
	 *            the date time value to be formatted into a date time string.
	 * @return the formatted date time string; an empty String if the input date
	 *         is <code>null</code> or if there is error during formatting.
	 */
	public static String formatDateMillis(Date date) {
		String dateTimeStr = "";
		DateFormat defaultDMF = new SimpleDateFormat(DEFAULT_DATEMILLIS_FORMAT);
		try {
			dateTimeStr = defaultDMF.format(date);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}

		return dateTimeStr;
	}

	/**
	 * Format the input date to a date time string in the following format: <br>
	 * <code>dd/MM/yyyy</code>
	 * 
	 * @param date
	 *            the date time value to be formatted into a date time string.
	 * @return the formatted date time string; an empty String if the input date
	 *         is <code>null</code> or if there is an error during formatting
	 */
	public static String formatDate(Date date) {
		String dateStr = "";
		DateFormat defaultDF = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
		try {
			dateStr = defaultDF.format(date);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}

		return dateStr;
	}

	/**
	 * Parse the input date to a <code>Date</code> object. The expected input
	 * date is of format <code>dd/MM/yyyy</code>
	 * 
	 * @param dateStr
	 *            the date string.
	 * @return the date instance parsed from the date string; <code>null</code>
	 *         if the date string is <code>null</code> or if the date string is
	 *         invalid
	 */
	public static Date parse(String dateStr) {
		if (dateStr.length() != 10) {
			return null;
		}
		Date date = null;
		DateFormat defaultDF = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
		// defaultDF.setLenient(true);
		try {
			date = defaultDF.parse(dateStr);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}

		return date;
	}

	public static Date parse(String dateStr, String format) {
		Date date = null;
		DateFormat defaultDF = new SimpleDateFormat(format);
		// defaultDF.setLenient(true);
		try {
			date = defaultDF.parse(dateStr);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}

		return date;
	}

	private static Date parseDate(String str, String[] parsePatterns) throws ParseException {
		if (str == null || parsePatterns == null) {
			throw new IllegalArgumentException("Date and Patterns must not be null");
		}

		SimpleDateFormat parser = null;
		ParsePosition pos = new ParsePosition(0);
		for (int i = 0; i < parsePatterns.length; i++) {
			if (i == 0) {
				parser = new SimpleDateFormat(parsePatterns[0]);
			} else {
				parser.applyPattern(parsePatterns[i]);
			}
			pos.setIndex(0);
			Date date = parser.parse(str, pos);
			if (date != null) {
				return date;
			}
		}
		throw new ParseException("Unable to parse the date: " + str, -1);
	}

	public static Date convertParse(String dateStr) {
		String[] parsePatterns = { DEFAULT_DATE_FORMAT, RFC3339_FORMAT };
		Date date;
		try {
			date = parseDate(dateStr, parsePatterns);
		} catch (ParseException e) {
			log.error("[MPA] error occurred: ERROR ", e);
			throw new RuntimeException(e);
		}
		return date;
	}

	public static Date getFullDate(Date date, Date time) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		Calendar timeCal = Calendar.getInstance();
		timeCal.setTime(time);

		cal.set(Calendar.HOUR_OF_DAY, timeCal.get(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE, timeCal.get(Calendar.MINUTE));
		cal.set(Calendar.SECOND, timeCal.get(Calendar.SECOND));

		return cal.getTime();
	}

	/**
	 * Parse the input date to a <code>java.sql.Timestamp</code> object. The
	 * expected input date is of format <code>dd/MM/yyyy</code> or
	 * <code>dd/MM/yyyy HH:mm:ss</code>
	 * 
	 * @param dateStr
	 *            the date string.
	 * @return the Timestamp instance created; <code>null</code> if the date
	 *         string is <code>null</code> or it does not conform to the format
	 *         <code>dd/MM/yyyy</code> or <code>dd/MM/yyyy HH:mm:ss</code>
	 */
	public static Timestamp parseTimestamp(String dateStr) {

		Timestamp tsDate = null;

		if (dateStr != null && dateStr.length() == 10) {
			dateStr += " 00:00:00";
		} else if (dateStr != null && dateStr.length() == 16) {
			dateStr += ":00";
		}
		DateFormat defaultDTF = new SimpleDateFormat(DEFAULT_DATETIME_FORMAT);
		try {
			if (dateStr != null) {
				Date date = defaultDTF.parse(dateStr);
				tsDate = new Timestamp(date.getTime());
			}
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}

		return tsDate;
	}

	/**
	 * Parse the input date to a <code>java.sql.Timestamp</code> object. The
	 * expected input date is of format <code>dd/MM/yyyy</code> or
	 * <code>dd/MM/yyyy HH:mm:ss</code>
	 * 
	 * @param dateStr
	 *            the date string.
	 * @return the Timestamp instance created; <code>null</code> if the date
	 *         string is <code>null</code> or it does not conform to the format
	 *         <code>dd/MM/yyyy</code> or <code>dd/MM/yyyy HH:mm:ss a</code>
	 */
	public static Timestamp parseAMTimestamp(String dateStr) {

		Timestamp tsDate = null;

		if (dateStr != null && dateStr.length() == 10) {
			dateStr += " 00:00:00 AM";
		} else if (dateStr != null && dateStr.length() == 16) {
			dateStr += ":00 AM";
		}
		DateFormat defaultAMDTF = new SimpleDateFormat(DEFAULT_DATETIME_AM_FORMAT);
		try {
			if (dateStr != null) {
				Date date = defaultAMDTF.parse(dateStr);
				tsDate = new Timestamp(date.getTime());
			}

		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}

		return tsDate;
	}

	/**
	 * Parse the input date to a <code>java.sql.Timestamp</code> object. The
	 * expected input date is of format <code>dd/MM/yyyy HH:mm:ss.SSS</code>
	 * 
	 * @param dateStr
	 *            the date string.
	 * @return the Timestamp instance created; <code>null</code> if the date
	 *         string is <code>null</code> or it does not conform to the format
	 *         <code>c HH:mm:ss.SSS</code>
	 */
	public static Timestamp parseDateMillis(String dateStr) {

		Timestamp tsDate = null;
		DateFormat defaultDMF = new SimpleDateFormat(DEFAULT_DATEMILLIS_FORMAT);
		try {
			if (dateStr != null && dateStr.length() > 23) {
				dateStr = dateStr.substring(0, 23);
			}
			if (dateStr != null) {
				Date date = defaultDMF.parse(dateStr);
				tsDate = new Timestamp(date.getTime());
			}
		} catch (Exception e) {
			log.error("[MPA] error occurred: ", e);
			// Do nothing
		}

		return tsDate;
	}

	public static Timestamp convertParseDateMillis(String dateStr) {

		Timestamp tsDate = null;
		DateFormat defaultDMF = new SimpleDateFormat(DEFAULT_DATEMILLIS_FORMAT);
		try {
			if (dateStr != null && dateStr.length() > 23)
				dateStr = dateStr.substring(0, 23);
			if (dateStr != null) {
				Date date = defaultDMF.parse(dateStr);
				tsDate = new Timestamp(date.getTime());
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

		return tsDate;
	}

	/**
	 * Format the input date to a date time string in the following format: <br>
	 * <code>dd/MM/yyyy HH:mm:ss.ffffff</code>
	 * 
	 * @param ts
	 *            the timestamp value to be formatted into a timestamp string.
	 * @return the formatted timestamp string; an empty String if the input date
	 *         is <code>null</code> or if there is error during formatting.
	 */
	public static String formatDateMicros(Timestamp ts) {
		String tsStr = "";

		try {
			tsStr = formatDateTime(ts);
			String micros = StringUtilPlus.lPad(Integer.toString(ts.getNanos()), 9, "0");
			micros = micros.substring(0, 6);
			tsStr += "." + micros;
		} catch (Exception e) {
			log.error("[MPA] error occurred: ", e);
			// Do nothing
		}

		return tsStr;
	}

	/**
	 * Tests the input value to ensure that a valid Date instance can be created
	 * from it. Roll over dates are not allowed here and will return a false
	 * value. Eg. isValidDate(2002, 10, 32) will return false.
	 * <p/>
	 * 
	 * @param year
	 *            The year value.
	 * @param month
	 *            The month value. ( 1 - 12 )
	 * @param day
	 *            The day value. ( 1 - 31 )
	 * @return True if all values can be used to create a single valid Date
	 *         instance.
	 */
	public static boolean isValidDate(int year, int month, int day) {

		if (day <= 0 || month <= 0 || year <= 0)
			return false;
		if (month > 12 || day > 31)
			return false;

		Calendar cal = Calendar.getInstance();
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, month - 1);

		// Find the maximum field value possible for the day with the year and
		// month.
		int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);

		return (day <= maxDay);
	}

	/**
	 * Tests the input string to ensure that a valid Date instance can be
	 * created according to the date format specified in the System property.
	 * <p/>
	 * If the properties file is not available or the dateformat property has
	 * not been specified, the default format "dd/MM/yyyy" will be used.
	 * <p/>
	 * 
	 * @param dateStr
	 *            A date string.
	 * @return True if it conforms to the system date format; False otherwise.
	 */
	public static boolean isValidDate(String dateStr) {

		if (dateStr == null)
			return false;
		if (dateStr.length() != 10) {
			return false;
		}

		boolean validDelimiter = (StringUtilPlus.getCount(dateStr, '-') == 2 || StringUtilPlus.getCount(dateStr, '/') == 2 || StringUtilPlus
				.getCount(dateStr, '.') == 2);

		if (!validDelimiter) {
			return false;
		}

		String dd = dateStr.substring(0, 2);
		String mm = dateStr.substring(3, 5);
		String yyyy = dateStr.substring(6, 10);

		try {
			return isValidDate(Integer.parseInt(yyyy), Integer.parseInt(mm), Integer.parseInt(dd));
		} catch (Throwable t) {
			log.error("[MPA] error occurred: ERROR ", t);
			return false;
		}

	}

	/**
	 * Tests if the inputs are valid time. When the ampm parameter is true, the
	 * input hour will be tested for 12-hour format ( 1 ? 12 ). When it is
	 * false, the input hour will be tested for 24-hour format ( 0 ? 23 ).
	 * <p/>
	 * 
	 * @param hour
	 *            The Hour value. ( 0 - 23 )
	 * @param minute
	 *            The Minute value. ( 0 - 59 )
	 * @return True if the time inputs can be used to create a valid time
	 *         instance.
	 */
	public static boolean isValidTime(int hour, int minute) {
		return minute >= 0 && minute <= 59 && hour >= 0 && hour <= 23;
	}

	/**
	 * get million seconds for input date
	 * 
	 * @param date
	 * @return million seconds
	 */
	public static long getMillis(Date date) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c.getTimeInMillis();
	}

	public static Date addSecond(Date date, int second) {
		if (date == null) {
			date = new Date();
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.SECOND, second);
		return c.getTime();
	}

	/**
	 * Parse the input datetime string to a <code>Date</code> object. The
	 * expected input date is of format <code>dd/MM/yyyy hh:mm:ss</code>
	 * 
	 * @param dateTimeStr
	 *            the date string.
	 * @return the date instance parsed from the date string; <code>null</code>
	 *         if the date string is <code>null</code> or if the date string is
	 *         invalid
	 */
	public static Date parseDateTime(String dateTimeStr) {
		Date date = null;
		DateFormat defaultDTF = new SimpleDateFormat(DEFAULT_DATETIME_FORMAT);
		try {
			date = defaultDTF.parse(dateTimeStr);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}
		return date;
	}

	/**
	 * Date Arithmetic function. Adds the specified (signed) amount of time to
	 * the given time field, based on the calendar's rules.
	 * <p/>
	 * For example, to subtract 5 days from a specific date, it can be achieved
	 * by calling:
	 * <p>
	 * DateUtil.add(date, Calendar.DATE, -5).
	 * <p/>
	 * 
	 * @param date
	 *            The date to perform the arithmetic function on
	 * @param field
	 *            A Calendar constant to retrieve the field value from the Date
	 * @param amount
	 *            the amount of date or time to be added to the field
	 * @return The date as a result of the execution of the arithmetic function.
	 */
	public static Date add(Date date, int field, int amount) {
		TimeZone tz = TimeZone.getTimeZone(default_timezone);
		Calendar cal = Calendar.getInstance(tz);
		cal.setTime(date);
		cal.add(field, amount);

		return cal.getTime();
	}

	public static Date parseDateTimeHHMM(String dateTimeStr) {
		Date date = null;
		DateFormat DATETIMEHHMM = new SimpleDateFormat(DATETIME_FORMAT_HHMM);
		try {
			date = DATETIMEHHMM.parse(dateTimeStr);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR, Correct format: " + DATETIME_FORMAT_HHMM + ", Current value: " + dateTimeStr);
		}
		return date;
	}

	public static String formatDateTimeYYYYdd(Date dateTimeStr) {
		String date = null;
		DateFormat DATETIMEHHMM = new SimpleDateFormat(DEFAULT_DATEYYYYDD_FORMAT);
		try {
			date = DATETIMEHHMM.format(dateTimeStr);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}
		return date;
	}

	public static String formatDateTimeEEEddMMYYYY(Date dateTimeStr) {
		String date = null;
		DateFormat DATETIMEHHMM = new SimpleDateFormat("EEE dd/MM/yyyy");
		try {
			date = DATETIMEHHMM.format(dateTimeStr);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}
		return date;
	}

	public static String formatDateTimeEEE(Date dateTimeStr) {
		String date = null;
		DateFormat DATETIMEHHMM = new SimpleDateFormat("EEE");
		try {
			date = DATETIMEHHMM.format(dateTimeStr);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}
		return date;
	}

	public static Date parseDateTimeYYYYdd(String dateTimeStr) {
		Date date = null;
		DateFormat DATETIMEHHMM = new SimpleDateFormat(DEFAULT_DATEYYYYDD_FORMAT);
		try {
			date = DATETIMEHHMM.parse(dateTimeStr);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}
		return date;
	}

	public static String formatDateHHMM(Date date) {
		String dateStr = "";
		DateFormat DATETIMEHHMM = new SimpleDateFormat(DATETIME_FORMAT_HHMM);
		try {
			dateStr = DATETIMEHHMM.format(date);
		} catch (Exception e) {
			log.error("[MPA] error occurred: ERROR ", e);
		}

		return dateStr;
	}

	public static String getPrintDate() {
		DateFormat printDF = new SimpleDateFormat(PRINT_DATE_FORMAT);
		return printDF.format(getDate());
	}

	public static java.sql.Date tringToNextDate(String str, int day) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		java.util.Date utilDate = sdf.parse(str);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(utilDate);
		calendar.add(Calendar.DATE, day);
		java.util.Date addUtilDate = calendar.getTime();
		return new java.sql.Date(addUtilDate.getTime());

	}

	/**
	 * Sting to Date
	 */
	public static java.sql.Date stringToDate(String str) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		java.util.Date utilDate = sdf.parse(str);
		return new java.sql.Date(utilDate.getTime());

	}

	/**
	 * Get the String value of Timestamp before current date, the String format
	 * is dd/MM/yyyy HH:mm
	 * 
	 * @return
	 */
	public static String formatLastDayHHMM() {
		Date yestoday = add(new Date(), Calendar.DATE, -1);
		return formatDateHHMM(yestoday);
	}

	/**
	 * Validate the dateTime format dd/MM/yyyy HH:mm
	 * 
	 * @param value
	 * @return
	 */
	public static boolean isValidDateTimeHHMM(String value) {
		try {
			if (StringUtilPlus.isEmpty(value) || value.length() != 16) {
				return false;
			}
			return (isValidDate(value.substring(0, 10)) && isValidTime(Integer.valueOf(value.substring(11, 13)),
					Integer.valueOf(value.substring(15))));
		} catch (NumberFormatException e) {
			log.error("[MPA] error occurred: ", e);
			return false;
		}
	}

	/**
	 * Validate the time format HH:mm:ss
	 * 
	 * @param value
	 * @return
	 */
	public static boolean isValidTime(String value) {
		if (value == null || value.length() != 8) {
			return false;
		}
		try {
			int hour = Integer.valueOf(value.substring(0, 2));
			int minute = Integer.valueOf(value.substring(3, 5));
			int second = Integer.valueOf(value.substring(6));
			return (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60);
		} catch (NumberFormatException e) {
			log.error("[MPA] error occurred: ", e);
		}
		return false;
	}

	/**
	 * get Current Month.
	 * 
	 * For example, if system date is '23/9/2012' then return "09"; if system
	 * date is '23/11/2012' then return "11";
	 * 
	 * @return String
	 */
	public static String getCurrentMonth() {
		TimeZone tz = TimeZone.getTimeZone(default_timezone);
		Calendar calendar = Calendar.getInstance(tz);
		int month = calendar.get(Calendar.MONTH) + 1;
		DecimalFormat df = new DecimalFormat(MONTH_FORMAT);
		return df.format(month);
	}

	/**
	 * get sub percentage day
	 * 
	 * @param startDt
	 * @param endDt
	 * @return
	 */
	public static double getDValueDay(Date startDt, Date endDt) {

		long duration = endDt.getTime() - startDt.getTime();
		return (double) duration / (24 * 60 * 60 * 1000);

	}

	/**
	 * get sub percentage day
	 * 
	 * @param startDt
	 * @param endDt
	 * @return
	 */
	public static int getDaysBetween(Date startDt, Date endDt) {

		long duration = endDt.getTime() - startDt.getTime();
		double douDay = (double) duration / (24 * 60 * 60 * 1000);

		return (int) Math.ceil(douDay);

	}

	/**
	 * transfer duration(milliseconds) to percentage day
	 * 
	 * @param duration
	 * @return
	 */
	public static double getPercentageDay(long duration) {
		return (double) duration / (24 * 60 * 60 * 1000);
	}

	/**
	 * used to validate time format
	 * 
	 * @param time
	 *            the format must be HH:mm
	 * @return
	 */
	public static String getReallyTime(String time) {

		if (time == null) {
			log.warn("time is null");
			return null;
		}

		time = time.replaceAll("-", "").trim();
		String[] timearry = time.split(":");
		if (timearry.length != 2) {
			log.warn("timearry.length != 2");
			return null;
		}

		String hour = timearry[0];
		String minute = timearry[1];
		if (StringUtils.isBlank(hour) || StringUtilPlus.isBlank(minute)) {
			log.warn("hour: " + hour + " or second: " + minute + " is blank!");
			return null;
		}

		try {
			int hhInt = Integer.parseInt(hour);
			int seInt = Integer.parseInt(minute);

			if (seInt > 59) {
				log.warn("minute > 59");
				return null;
			}
			if (hhInt > 24) {
				log.warn("hour > 24");
				return null;
			}
			if (hhInt == 24 && seInt > 0) {
				log.warn("minute must equal 0 when hour is 24");
				return null;
			}
			return time;
		} catch (Exception ex) {
			log.error("[MPA] error occurred: ", ex);
		}

		return null;
	}

	public static int getYear() {
		TimeZone tz = TimeZone.getTimeZone(default_timezone);
		Calendar calendar = Calendar.getInstance(tz);
		return calendar.get(Calendar.YEAR);
	}

	public static Timestamp getNextIntervalDay(Date date, int days) {
		TimeZone tz = TimeZone.getTimeZone(default_timezone);
		Calendar cal = Calendar.getInstance(tz);
		cal.setTime(date);
		cal.add(Calendar.DATE, days);
		return new Timestamp(cal.getTimeInMillis());
	}

	public static int getDaysBetween(java.util.Calendar d1, java.util.Calendar d2) {
		if (d1.after(d2)) { // swap dates so that d1 is start and d2 is end
			java.util.Calendar swap = d1;
			d1 = d2;
			d2 = swap;
		}
		int days = d2.get(java.util.Calendar.DAY_OF_YEAR) - d1.get(java.util.Calendar.DAY_OF_YEAR);
		int y2 = d2.get(java.util.Calendar.YEAR);
		if (d1.get(java.util.Calendar.YEAR) != y2) {
			d1 = (java.util.Calendar) d1.clone();
			do {
				days += d1.getActualMaximum(java.util.Calendar.DAY_OF_YEAR);
				d1.add(java.util.Calendar.YEAR, 1);
			} while (d1.get(java.util.Calendar.YEAR) != y2);
		}
		return days;
	}

	public static int getIntervalHours(Timestamp t1, Timestamp t2) {
		return Integer.parseInt(Long.toString((t2.getTime() - t1.getTime()) / (60 * 60)));
	}

	/**
	 * get Next date, Only keep year,
	 * 
	 * @param date
	 * @param days
	 * @return
	 */
	public static Date getNext_yyyyMMdd_Dt(Date date, int days) {

		TimeZone tz = TimeZone.getTimeZone(default_timezone);
		Calendar calendar = Calendar.getInstance(tz);
		calendar.setTime(date);
		calendar.add(Calendar.DATE, days);

		Calendar result = Calendar.getInstance(tz);
		result.clear();

		result.set(Calendar.YEAR, calendar.get(Calendar.YEAR));
		result.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
		result.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH));

		return result.getTime();
	}

	public static void main(String[] args) {
		System.out.println(parse("99/99/2013"));
	}

}
